<template>
  <div
    class="invite-together-container"
    id="container"
    :style="{
      top: componentContainerHeight - 2 * componentContainerHeight - bottom + 'px',
      opacity: componentContainerHeight ? 1 : 0
    }"
    v-if="monitoring"
  >
    <!-- 左侧邀请按钮 -->
    <span class="invite-button">
      <span class="close-invite" @click="closeInvite" v-if="isInviter.getValue() && !seatNumber.getValue()"
        ><svg-icon name="close" class="close" size="40rpx"></svg-icon>
      </span>
      <span class="invite-text">{{
        isInviter.getValue() ? (seatNumber.getValue() ? '堂食点餐中' : '结束多人点餐') : '一起点餐中'
      }}</span>
    </span>

    <!-- 右侧头像和人数区域 -->
    <div class="participants">
      <div class="avatars-container">
        <div v-for="(avatar, index) in displayedAvatars" :key="index" class="avatar-item">
          <img :src="avatar" alt="参与者头像" class="avatar-img" />
        </div>
        <div v-if="hasExtraParticipants" class="extra-count">+{{ extraCount }}</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, getCurrentInstance, onMounted, ref, watch } from 'vue'
import SvgIcon from '@/components/SvgIcon/index.vue'
import { SSEConnection } from '@/utils/SSE'
import { SSEMessageType } from '@/enum/SSEMessageType'
import type { CartItemVO } from '@/types/response/shopping-cart'
import $store from '@/store'
import $API from '@/api'
import type { UserInfo } from '@/types/response/user'
import { $modal } from '@/plugins'
// 接收props
defineProps({
  bottom: {
    type: Number,
    default: 0
  }
})
const componentContainerHeight = ref()
const monitoring = ref(false)
let sse: null | SSEConnection = null
const instance = getCurrentInstance()
const { shopId, seatNumber, isInviter } = $store.shop
onMounted(async () => {
  processingContainerHeight()
})
// 动态获取组件高度，失败则50ms后重试，直到成功，获取到后停止
function processingContainerHeight() {
  let timer: number | null = null
  const tryGet = () => {
    let elementQuery = uni.createSelectorQuery().in(instance)
    elementQuery
      .select('#container')
      .fields({ scrollOffset: true, size: true, dataset: true, rect: true, id: true }, (res: any) => {
        if (res && res.height) {
          componentContainerHeight.value = res.height
          console.log('Container height:', componentContainerHeight.value)
          if (timer) clearTimeout(timer)
        } else {
          timer = setTimeout(tryGet, 50)
        }
      })
      .exec()
  }
  tryGet()
}
// 接收的数据
const listener = ref<UserInfo[]>([])
// 实际项目中应该从store或API获取
const participants = computed(() => listener.value.map((e) => e.avatar))

// 计算属性：最多显示3个头像
const displayedAvatars = computed(() => participants.value.slice(0, 3))
// 计算属性：是否有额外参与者
const hasExtraParticipants = computed(() => participants.value.length > 3)
// 计算属性：额外参与者数量
function closeSSEConnection() {
  if (sse != null) {
    console.log('stop listen cart change')
    sse.close()
    sse = null
  }
  monitoring.value = false
}
const extraCount = computed(() => participants.value.length - 3)
watch(
  [$store.shop.shopId.getRef(), $store.shop.inviteCode.getRef(), $store.shop.seatNumber.getRef()],
  ([shopId, inviteCode, seatNumber]) => {
    console.log('listen [shopId, inviteCode, seatNumber] changed !', shopId, inviteCode, seatNumber)
    if (inviteCode != null || seatNumber != null) {
      console.log('开始监听购物车变化')
      // 当接收到来自其它同时点餐人修改购物车事件时刷新购物车
      ;(sse = new SSEConnection({
        path: `/shop/sse/shopping-cart/on?shopId=${shopId || ''}&seatNumber=${seatNumber || ''}&inviteCode=${inviteCode || ''}`
      }))
        .onOpen(() => {
          console.log('open success!')
          $store.cart.shoppingCartRefreshEvent.emit()
        })
        .subscriber((subscriber) => {
          subscriber
            .subscribe<CartItemVO[]>(SSEMessageType.SHOPPING_CART_CHANGE, () => {
              console.log('接收SSE通知刷新购物车')
              $store.cart.shoppingCartRefreshEvent.emit()
            })
            .subscribe<UserInfo[]>(SSEMessageType.BROTHER_INFOS, ({ data }) => {
              console.log('监听者', data)
              listener.value = data
            })
            .subscribe<void>(SSEMessageType.INVITE_END, () => {
              console.log('接收到已结束多人模式')
              $store.shop.inviteCode.clearValue()
              $modal.toastMsg('多人点餐已结束')
            })
        })
        .onFail(() => {
          $modal.toastMsg('邀请链接过期了~')
          closeSSEConnection()
          $store.shop.inviteCode.clearValue()
        })
        .onClose(() => {
          $store.cart.shoppingCartRefreshEvent.emit()
          console.log('sse close')
        })
        .start()
      monitoring.value = true
    } else {
      closeSSEConnection()
    }
  },
  { immediate: true }
)

async function closeInvite() {
  // 结束
  await $API.shop.offMulti(shopId.getValue()!)
  $store.shop.inviteCode.clearValue()
  monitoring.value = false
}
</script>

<style scoped lang="scss">
$avatar-size: 50rpx;

.invite-together-container {
  position: absolute;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20rpx;
  width: 100%;
  height: $avatar-size * 1.8;
  border-radius: 16rpx;
  background-color: #fff;
  box-shadow: 0 6rpx 16rpx rgb(0 0 0 / 11.4%);
  transition: all 0.3s ease-in-out;
  box-sizing: border-box;
}

.invite-button {
  display: flex;
  align-items: center;
  font-size: 28rpx;
  border: none;
  color: rgb(72 72 72);
  transition: background-color 0.2s;

  .close-invite {
    display: flex;
    align-items: center;
  }

  .invite-text {
    margin-left: 10rpx;
  }

  .separate {
    margin: 0 24rpx;
  }
}

.invite-icon {
  margin-right: 12rpx;
}

.participants {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  flex-grow: 1;
}

.avatars-container {
  display: flex;
  align-items: center;
}

.avatar-item {
  overflow: hidden;
  margin-left: -16rpx;
  width: $avatar-size;
  height: $avatar-size;
  border: 4rpx solid white;
  border-radius: 50%;
  box-shadow: 0 0 0 2rpx rgb(0 0 0 / 10%);

  &:first-child {
    margin-left: 0;
  }
}

.avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.extra-count {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-left: -16rpx;
  width: $avatar-size;
  height: $avatar-size;
  font-size: 24rpx;
  border: 4rpx solid white;
  border-radius: 50%;
  color: #606266;
  background-color: #f5f5f5;
  box-shadow: 0 0 0 2rpx rgb(0 0 0 / 10%);
}
</style>
